import React from 'react';
import classNames from 'classnames';
import Icon from '../Icon';
import DatePciker from './Date';
import Button from '../Button';
import Time from '../Time/Time';
import './DateTime.less';
import Dom from '../utils/Dom';
import {dateFormat, parseDate, alignPostion} from '../utils/Utils';

class DateTime extends React.Component {
    static displayName = 'DateTime';

    static defaultProps = {
        type: 'date'
    }

    constructor (props) {
        super(props);
        const v = this.initDateValue();
        const current = props.value ? new Date(v) : new Date();
        this.state = {
            current,
            open: false,
            optionStyle: {},
            view: this.getDefaultView(props.type)
        };
    }

    initDateValue () {
        const {value} = this.props;
        const format = this.initFormat();
        let v;
        if (value && typeof value === 'string' || typeof value === 'number') {
            v = parseDate(format, `${value}`);
        }
        if (value && value instanceof Date) {
            v = new Date(value);
        }
        return v;
    }

    initFormat () {
        let {format, type} = this.props;
        if (type === 'year' && !format) {
            format = 'yyyy';
        }
        if (type === 'month' && !format) {
            format = 'yyyy-MM';
        }
        if (type === 'datetime' && !format) {
            format = 'yyyy-MM-dd hh:mm:ss';
        }
        format = format || 'yyyy-MM-dd';
        return format;
    }

    getTimeFormat () {
        const format = this.initFormat();
        if (/(h+).*(m+).*(s+).*/.test(format)) {
            return format.match(/(h+).*(m+).*(s+)/)[0];
        }
        if (/(h+).*(m+).*/.test(format)) {
            return format.match(/(h+).*(m+)/)[0];
        }
        if (/(h+).*/.test(format)) {
            return format.match(/(h+).*/)[0];
        }
        return null;
    }

    formatValue (format, date) {
        return dateFormat(format, date);
    }

    onPrevYear = (current) => {
        this._isMounted && this.setState({
            current
        });
    }

    onNextYear = (current) => {
        this._isMounted && this.setState({
            current
        });
    }

    onPrevMonth = (current) => {
        this._isMounted && this.setState({
            current
        });
    }

    onNextMonth = (current) => {
        this._isMounted && this.setState({
            current
        });
    }

    onChange = (date) => {
        const val = this.formatValue(this.initFormat(), date);
        this.props.onChange && this.props.onChange(val);
        this.close();
    }

    onChangeMonth = (date) => {
        if (this.props.type === 'month') {
            const val = this.formatValue(this.initFormat(), date);
            this.props.onChange && this.props.onChange(val);
            this.close();
        }
        if (this.props.type === 'date') {
            window.setTimeout(() => {
                this._isMounted && this.setState({
                    current: date,
                    view: 'date'
                });
            });
        }
    }

    onChangeYear = (date) => {
        if (this.props.type === 'year') {
            const val = this.formatValue(this.initFormat(), date);
            this.props.onChange && this.props.onChange(val);
            this.close();
        } else {
            window.setTimeout(() => {
                this._isMounted && this.setState({
                    current: date,
                    view: 'month'
                });
            });
        }
    }

    componentDidMount () {
        this._isMounted = true;
        document.addEventListener('click', this.clickAnyWhere.bind(this), false);
    }

    componentWillUnmount () {
        this._isMounted = false;
        document.removeEventListener('click', this.clickAnyWhere);
    }

    clickAnyWhere (e) {
        const ele = e.target || e.srcElement;
        const parent = Dom.closest(ele, '.cm-datetime');
        if (parent && parent == this.wrap) {
            return ;
        } else {
            this._isMounted && this.setState({
                open: false
            });
        }
    }

    onShowHide = (e) => {
        const {disabled, align} = this.props;
        const ele = e.target || e.srcElement;
        // click clear icon
        if (ele.tagName === 'I' && ele.className.indexOf('cm-datetime-clear') !== -1) {
            return;
        }
        if (disabled) {
            return;
        }
        const open = this.state.open;
        this._isMounted && this.setState({
            open: !open
        }, () => {
            const optionStyle = alignPostion(align, this.rel, this.dropdown);
            this.setState({
                optionStyle
            });
        });
    }

    close () {
        this._isMounted && this.setState({
            open: false
        });
    }

    getDefaultView () {
        const {type} = this.props;
        switch (type) {
            case 'date' : {
                return 'date';
            }
            case 'year' : {
                return 'year';
            }
            case 'month' : {
                return 'month';
            }
            default : {
                return 'date';
            }
        }
    }

    onGotoMonthView = () => {
        window.setTimeout(() => {
            this._isMounted && this.setState({
                view: 'month'
            });
        });
    }

    onGotoYearView = () => {
        window.setTimeout(() => {
            this._isMounted && this.setState({
                view: 'year'
            });
        });
    }

    onClear = () => {
        this.props.onChange && this.props.onChange('');
    }

    onShortCutClick = (item) => {
        if (item.value && typeof item.value === 'function') {
            const val = this.formatValue(this.initFormat(), item.value());
            this.props.onChange && this.props.onChange(val);
            if (item.onClick) {
                item.onClick();
            }
            this.close();
        }
    }

    renderShortCuts = () => {
        return this.props.shortcuts.map((item, index) => {
            return <div className='cm-datetime-shortcut-item' key={index} onClick={this.onShortCutClick.bind(this, item)}>{item.text}</div>;
        });
    }

    toggleTimeAndDate = () => {
        const view = this.state.view === 'date' ? 'time' : 'date';
        this._isMounted && this.setState({
            view
        });
    }

    onChangeTime = (current) => {
        const {value, onChange} = this.props;
        let v;
        if (!value) {
            v = this.state.current;
        } else {
            let val = this.props.value;
            if (this.props.value instanceof Date) {
                val = this.formatValue(this.initFormat(), this.props.value);
            }
            v = parseDate(this.initFormat(), val);
        }
        v.setHours(current[0]);
        v.setMinutes(current[1]);
        v.setSeconds(current[2]);
        onChange && onChange(this.formatValue(this.initFormat(), v));
    }

    render () {
        const {className, style, theme, disabled, align, name, type, value, shortcuts,
            placeholder, size, disabledDate, disabledPrev, disabledNext, clearable} = this.props;
        const clazzName = classNames(className, 'cm-datetime', {
            'cm-datetime-disabled': disabled,
            [`cm-datetime-${align}`]: align,
            [`cm-datetime-${theme}`]: theme,
            [`cm-datetime-${size}`]: size,
            'cm-datetime-clearable': !disabled && clearable && value !== '',
            'cm-datetime-open': this.state.open,
            'cm-datetime-has-shortcuts': shortcuts
        });
        const format = this.initFormat();

        const v = this.initDateValue();
        const val = value ? this.formatValue(format, v) : '';
        const text = value ? dateFormat(format, new Date(v)) : (placeholder ? placeholder : '');

        const timeCurrent = [v.getHours(), v.getMinutes(), v.getSeconds()];
        const timeFormat = type === 'datetime' ? this.getTimeFormat() : undefined;
        
        return <div className={clazzName} style={style} ref={f => this.wrap = f}>
            <div className='cm-datetime-value' onClick={this.onShowHide} tabIndex='0' ref={f => this.rel = f}>
                <input type='hidden' name={name} value={val} />
                <div className='cm-datetime-text'>{text}</div>
                <Icon name='calendar' className='cm-datetime-cert'/>
                {
                    clearable
                        ? <Icon name='x-circle' className='cm-datetime-clear' onClick={this.onClear}/>
                        : null
                }
            </div>
            <div className='cm-datetime-wrap' ref={f => this.dropdown = f} style={this.state.optionStyle}>
                {
                    shortcuts
                        ? <div className='cm-datetime-shortcuts'>
                            {this.renderShortCuts()}
                        </div>
                        : null
                }
                {
                    this.state.view === 'time'
                        ? null
                        : <DatePciker type={type} view={this.state.view} value={v} current={this.state.current} 
                            onPrevYear={this.onPrevYear} onNextYear={this.onNextYear} onPrevMonth={this.onPrevMonth} 
                            onSelectMonth={this.onChangeMonth} onSelectYear={this.onChangeYear} gotoYearView={this.onGotoYearView}
                            onNextMonth={this.onNextMonth} onChange={this.onChange} gotoMonthView={this.onGotoMonthView}
                            disabledDate={disabledDate} disabledPrev={disabledPrev} disabledNext={disabledNext}/>
                }
                {
                    type === 'datetime' && this.state.view === 'time'
                        ? <Time format={timeFormat} current={timeCurrent} onChange={this.onChangeTime}/>
                        : null
                }
                {
                    type === 'datetime'
                        ? <div className='cm-datetime-tools'>
                            <Button size='small' theme='text' onClick={this.toggleTimeAndDate}>{
                                this.state.view === 'time' ? '选择日期' : '选择时间'
                            }</Button>
                        </div>
                        : null
                }
            </div>
        </div>;
    }
}

export default DateTime;
